package cn.cdu.medical.service.impl;

import cn.cdu.data.entity.User;
import cn.cdu.data.service.IUserService;
import cn.cdu.medical.entity.MedicalRecord;
import cn.cdu.medical.repository.MedicalRecordMapper;
import cn.cdu.medical.service.ConsultationService;
import cn.cdu.medical.service.MedicalRecordService;
import cn.cdu.doctor.entity.HospitalOrder;
import cn.cdu.doctor.service.IHospitalOrderService;
import cn.cdu.doctor.entity.Doctor;
import cn.cdu.doctor.service.IDoctorService;
import cn.cdu.basics.exception.BusinessException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 病历记录服务实现类
 */
@Slf4j
@Service
@Transactional
public class MedicalRecordServiceImpl extends ServiceImpl<MedicalRecordMapper, MedicalRecord> implements MedicalRecordService {

    @Autowired
    private ConsultationService consultationService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IHospitalOrderService hospitalOrderService;

    @Autowired
    private IDoctorService doctorService;

    // 添加病历号生成辅助方法
    private String generatePatientFileNumber(String userId) {
        return "P" + userId.substring(Math.max(0, userId.length() - 10));
    }

    // 添加门诊号生成辅助方法
    private String generateOutpatientNumber(String userId) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String datePrefix = LocalDateTime.now().format(formatter);
        return "C" + datePrefix + userId.substring(Math.max(0, userId.length() - 5));
    }

    // 获取患者真实姓名的辅助方法
    private String getPatientRealName(String patientId) {
        try {
            User user = userService.getById(patientId);
            if (user != null && user.getNickname() != null && !user.getNickname().isEmpty()) {
                return user.getNickname();
            }
        } catch (Exception e) {
            log.error("Error getting patient real name: ", e);
        }
        // 如果出错或未找到用户，返回默认名称
        return "患者_" + patientId.substring(Math.max(0, patientId.length() - 4));
    }

    @Override
    @Transactional
    public MedicalRecord generateInitialMedicalRecord(String consultationId) {
        try {
            log.debug("Generating initial medical record for consultation: {}", consultationId);

            // 通过问诊服务生成初始病历
            MedicalRecord record = consultationService.generateInitialMedicalRecord(consultationId);

            // 设置就诊时间和类型
            record.setVisitTime(LocalDateTime.now());
            record.setVisitType("初诊");

            // 设置创建人为患者姓名
            String patientName = getPatientRealName(record.getUserId());
            record.setCreateBy(patientName);
            record.setCreateTime(new Date());

            // 保存病历记录
            save(record);
            log.debug("Saved medical record: {}", record);

            return record;
        } catch (Exception e) {
            log.error("Error generating initial medical record: ", e);
            throw new RuntimeException("Failed to generate initial medical record: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public MedicalRecord update(MedicalRecord record) {
        try {
            log.debug("Updating medical record: {}", record);

            // 获取原有记录
            MedicalRecord existing = getById(record.getId());
            if (existing == null) {
                throw new RuntimeException("Medical record not found: " + record.getId());
            }

            // 保留原有记录的必要字段
            if (record.getOrderId() == null) {
                record.setOrderId(existing.getOrderId());
            }
            if (record.getUserId() == null) {
                record.setUserId(existing.getUserId());
            }
            if (record.getDoctorId() == null) {
                record.setDoctorId(existing.getDoctorId());
            }
            if (record.getConsultationId() == null) {
                record.setConsultationId(existing.getConsultationId());
            }
            if (record.getPatientName() == null) {
                record.setPatientName(existing.getPatientName());
            }
            if (record.getGender() == null) {
                record.setGender(existing.getGender());
            }
            if (record.getAge() == null) {
                record.setAge(existing.getAge());
            }
            if (record.getPatientFileNumber() == null) {
                record.setPatientFileNumber(existing.getPatientFileNumber());
            }
            if (record.getOutpatientNumber() == null) {
                record.setOutpatientNumber(existing.getOutpatientNumber());
            }
            if (record.getVisitTime() == null) {
                record.setVisitTime(existing.getVisitTime());
            }
            if (record.getVisitType() == null) {
                record.setVisitType(existing.getVisitType());
            }
            if (record.getDeptName() == null) {
                record.setDeptName(existing.getDeptName());
            }
            if (record.getDoctorName() == null) {
                record.setDoctorName(existing.getDoctorName());
            }
            if (record.getDiagnosisType() == null) {
                record.setDiagnosisType(existing.getDiagnosisType());
            }
            if (record.getDiagnosisCode() == null) {
                record.setDiagnosisCode(existing.getDiagnosisCode());
            }

            // 保留恢复建议相关字段
            if (record.getAdviceType() == null) {
                record.setAdviceType(existing.getAdviceType());
            }
            if (record.getAdviceTitle() == null) {
                record.setAdviceTitle(existing.getAdviceTitle());
            }
            if (record.getAdviceContent() == null) {
                record.setAdviceContent(existing.getAdviceContent());
            }

            // 更新记录
            updateById(record);
            log.debug("Updated medical record: {}", record);

            return record;
        } catch (Exception e) {
            log.error("Error updating medical record: ", e);
            throw new RuntimeException("Failed to update medical record: " + e.getMessage());
        }
    }

    @Override
    public List<MedicalRecord> getUserMedicalRecords(String userId) {
        try {
            log.debug("Getting medical records for user: {}", userId);

            List<MedicalRecord> records = baseMapper.findByUserId(userId);
            log.debug("Found {} medical records for user {}", records.size(), userId);

            return records;
        } catch (Exception e) {
            log.error("Error getting user medical records: ", e);
            throw new RuntimeException("Failed to get user medical records: " + e.getMessage());
        }
    }

    @Override
    public List<MedicalRecord> getDoctorMedicalRecords(String doctorId) {
        try {
            log.debug("Getting medical records for doctor: {}", doctorId);

            List<MedicalRecord> records = baseMapper.findByDoctorId(doctorId);
            log.debug("Found {} medical records for doctor {}", records.size(), doctorId);

            return records;
        } catch (Exception e) {
            log.error("Error getting doctor medical records: ", e);
            throw new RuntimeException("Failed to get doctor medical records: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public MedicalRecord createMedicalRecord(MedicalRecord record) {
        try {
            log.debug("Creating new medical record: {}", record);

            // 设置默认值
            if (record.getVisitTime() == null) {
                record.setVisitTime(LocalDateTime.now());
            }

            if (record.getVisitType() == null) {
                record.setVisitType("初诊");
            }

            // 保存记录
            save(record);
            log.debug("Created medical record: {}", record);

            return record;
        } catch (Exception e) {
            log.error("Error creating medical record: ", e);
            throw new RuntimeException("Failed to create medical record: " + e.getMessage());
        }
    }

    @Override
    public MedicalRecord getMedicalRecordDetail(String id) {
        try {
            log.debug("Getting medical record detail: {}", id);

            MedicalRecord record = getById(id);
            if (record == null) {
                throw new RuntimeException("Medical record not found: " + id);
            }

            log.debug("Found medical record: {}", record);

            return record;
        } catch (Exception e) {
            log.error("Error getting medical record detail: ", e);
            throw new RuntimeException("Failed to get medical record detail: " + e.getMessage());
        }
    }

    /**
     * 根据问诊ID获取或创建病历
     * @param consultationId 问诊ID
     * @return 病历记录
     */
    public MedicalRecord getOrCreateMedicalRecordByConsultationId(String consultationId) {
        try {
            log.debug("Getting or creating medical record for consultation: {}", consultationId);

            // 查找是否已存在关联的病历
            MedicalRecord existingRecord = baseMapper.findByConsultationId(consultationId);

            // 如果存在则直接返回
            if (existingRecord != null) {
                log.debug("Found existing medical record: {}", existingRecord);
                return existingRecord;
            }

            // 不存在则创建新的初始病历
            log.debug("No existing medical record found, generating a new one");
            return generateInitialMedicalRecord(consultationId);
        } catch (Exception e) {
            log.error("Error getting or creating medical record: ", e);
            throw new RuntimeException("Failed to get or create medical record: " + e.getMessage());
        }
    }

    @Override
    public MedicalRecord getCurrentMedicalRecord(String orderId) {
        try {
            log.debug("Getting current medical record for order: {}", orderId);

            // 首先获取挂号记录 orderId是数据库中的id不是order_id
            HospitalOrder order = hospitalOrderService.getById(orderId);
            if (order == null) {
                log.error("Order not found for ID: {}", orderId);
                throw new BusinessException("挂号记录不存在");
            }

            // 查询病历记录
            QueryWrapper<MedicalRecord> query = new QueryWrapper<>();
            query.eq("order_id", order.getOrderId())
                .eq("del_flag", 0)
                .orderByDesc("create_time")
                .last("LIMIT 1");

            MedicalRecord record = getOne(query);

            if (record == null) {
                // 如果没有找到任何病历，创建一个新的
                log.info("No medical record found for order {}, creating a new one", orderId);
                record = new MedicalRecord();
                record.setOrderId(order.getOrderId());
                record.setUserId(order.getUserId());
                record.setDoctorId(order.getDoctorId());
                record.setVisitTime(LocalDateTime.now());
                record.setVisitType("初诊");
                record.setDelFlag(0);
            }

            // 填充或更新基本信息
            updatePatientInfo(record, orderId);

            // 如果是新记录，保存到数据库
            if (record.getId() == null) {
                save(record);
                log.info("Created new record: {}", record);
            } else {
                // 如果是更新记录，保存更新
                updateById(record);
                log.info("Updated record: {}", record);
            }

            log.debug("Final medical record: {}", record);
            return record;
        } catch (Exception e) {
            log.error("Error getting current medical record: ", e);
            throw new RuntimeException("Failed to get current medical record: " + e.getMessage());
        }
    }

    /**
     * 计算年龄
     * @param birthDate 出生日期
     * @return 计算出的年龄，如果出生日期为空则返回null
     */
    private Integer calculateAge(Date birthDate) {
        if (birthDate == null) {
            return null;
        }

        try {
            LocalDateTime birthDateTime = LocalDateTime.ofInstant(
                birthDate.toInstant(), java.time.ZoneId.systemDefault());
            LocalDateTime now = LocalDateTime.now();

            long years = java.time.temporal.ChronoUnit.YEARS.between(birthDateTime, now);
            return (int) years;
        } catch (Exception e) {
            log.error("Error calculating age from birth date: {}", birthDate, e);
            return null;
        }
    }

    /**
     * 更新病历记录中的患者信息
     * @param record 病历记录
     * @param orderId 挂号ID
     */
    private void updatePatientInfo(MedicalRecord record, String orderId) {
        try {
            // 先获取挂号记录
            HospitalOrder order = hospitalOrderService.getById(orderId);
            if (order == null) {
                log.error("Order not found for ID: {}", orderId);
                throw new BusinessException("挂号记录不存在");
            }

            // 查询用户真实信息
            User user = userService.getById(order.getUserId());
            if (user != null) {
                // 强制更新患者姓名为真实姓名
                String realName = user.getNickname();
                if (realName != null && !realName.isEmpty()) {
                    if (!realName.equals(record.getPatientName())) {
                        log.info("Updating patient name from '{}' to '{}'", record.getPatientName(), realName);
                        record.setPatientName(realName);
                    }
                }

                // 更新性别
                if (user.getSex() != null && !user.getSex().isEmpty()) {
                    record.setGender(user.getSex());
                } else if (record.getGender() == null || record.getGender().isEmpty()) {
                    record.setGender("男");
                }

                // 根据出生日期计算并更新年龄
                Integer calculatedAge = calculateAge(user.getBirth());
                if (calculatedAge != null) {
                    log.info("Calculated age from birth date: {} years", calculatedAge);
                    record.setAge(calculatedAge);
                } else if (record.getAge() == null) {
                    // 如果无法计算年龄且病历中没有年龄信息，设置默认值
                    log.warn("Unable to calculate age from birth date, using default age");
                    record.setAge(40);
                }

                // 更新档案号和门诊号
                String patientIdSuffix = user.getId().substring(Math.max(0, user.getId().length() - 10));
                if (record.getPatientFileNumber() == null || record.getPatientFileNumber().isEmpty()) {
                    record.setPatientFileNumber("P" + patientIdSuffix);
                    log.info("Generated patient file number: {}", record.getPatientFileNumber());
                }

                if (record.getOutpatientNumber() == null || record.getOutpatientNumber().isEmpty()) {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String datePrefix = LocalDateTime.now().format(formatter);
                    record.setOutpatientNumber("C" + datePrefix + patientIdSuffix.substring(0, 5));
                    log.info("Generated outpatient number: {}", record.getOutpatientNumber());
                }
            } else {
                log.warn("User not found for ID: {}", order.getUserId());
                // 设置默认值
                if (record.getPatientName() == null || record.getPatientName().isEmpty()) {
                    record.setPatientName(order.getUserName());
                }
                if (record.getGender() == null || record.getGender().isEmpty()) {
                    record.setGender("男");
                }
                if (record.getAge() == null) {
                    record.setAge(40);
                }
            }

            // 更新其他信息
            if (record.getDeptName() == null || record.getDeptName().isEmpty()) {
                record.setDeptName("普通内科");
            }

            if (record.getDiagnosisType() == null || record.getDiagnosisType().isEmpty()) {
                record.setDiagnosisType("西医");
            }

            if (record.getDiagnosisName() == null || record.getDiagnosisName().isEmpty()) {
                record.setDiagnosisName("待诊断");
            }
        } catch (Exception e) {
            log.error("Error updating patient info: ", e);
        }
    }

    @Override
    public List<MedicalRecord> getPatientHistoryRecords(String patientId, String doctorId, String deptName) {
        try {
            log.debug("Getting history medical records for patient: {}, doctor: {}, department: {}",
                     patientId, doctorId, deptName);

            List<MedicalRecord> records = baseMapper.findPatientHistoryRecords(patientId, doctorId, deptName);

            // 按就诊时间倒序排序
            records.sort((a, b) -> b.getVisitTime().compareTo(a.getVisitTime()));

            log.debug("Found {} history medical records for patient {}", records.size(), patientId);

            return records;
        } catch (Exception e) {
            log.error("Error getting patient history medical records: ", e);
            throw new RuntimeException("Failed to get patient history medical records: " + e.getMessage());
        }
    }

    /**
     * 获取医生科室的病历列表
     * @param doctorId 医生ID
     * @param deptName 科室名称
     * @return 病历列表
     */
    public List<MedicalRecord> getDepartmentRecords(String doctorId, String deptName) {
        try {
            log.debug("Getting department records for doctor: {}, department: {}", doctorId, deptName);

            List<MedicalRecord> records = baseMapper.findByDoctorDepartment(doctorId, deptName);
            log.debug("Found {} records in department {}", records.size(), deptName);

            return records;
        } catch (Exception e) {
            log.error("Error getting department records: ", e);
            throw new RuntimeException("Failed to get department records: " + e.getMessage());
        }
    }

    @Override
    public MedicalRecord getOrCreateByOrderId(String orderId) {
        log.info("Getting or creating medical record for order ID: {}", orderId);

        try {
            // 通过orderId查询病历
            QueryWrapper<MedicalRecord> query = new QueryWrapper<>();
            query.eq("order_id", orderId)
                .eq("del_flag", 0);  // 只查询未删除的记录
            MedicalRecord record = getOne(query);

            // 如果找到，直接返回
            if (record != null) {
                log.info("Found existing medical record: {} for order ID: {}", record.getId(), orderId);
                return record;
            }

            // 如果未找到，则创建新病历
            HospitalOrder order = hospitalOrderService.getById(orderId);
            if (order == null) {
                log.error("Order not found for ID: {}", orderId);
                throw new BusinessException("挂号记录不存在");
            }

            // 创建新病历记录
            record = new MedicalRecord();
            record.setId(String.valueOf(System.currentTimeMillis())); // 设置ID
            record.setUserId(order.getUserId());
            record.setDoctorId(order.getDoctorId());
            record.setOrderId(order.getOrderId());
            record.setVisitTime(LocalDateTime.now());
            record.setPatientName(order.getUserName());

            // 设置医生姓名和科室
            try {
                Doctor doctor = doctorService.getById(order.getDoctorId());
                if (doctor != null) {
                    record.setDoctorName(doctor.getDoctorName());
                    record.setDeptName(doctor.getSubjectName());
                } else {
                    log.warn("Doctor not found for ID: {}", order.getDoctorId());
                    record.setDoctorName(order.getDoctorName());
                }
            } catch (Exception e) {
                log.warn("Error getting doctor info for ID: {}", order.getDoctorId(), e);
                record.setDoctorName(order.getDoctorName());
            }

            // 设置患者信息
            try {
                User user = userService.getById(order.getUserId());
                if (user != null) {
                    record.setGender(user.getSex());

                    // 通过生日计算年龄
                    if (user.getBirth() != null) {
                        try {
                            LocalDateTime birthDateTime = LocalDateTime.ofInstant(
                                user.getBirth().toInstant(), java.time.ZoneId.systemDefault());
                            LocalDateTime now = LocalDateTime.now();

                            long years = java.time.temporal.ChronoUnit.YEARS.between(birthDateTime, now);
                            record.setAge((int) years);
                        } catch (Exception e) {
                            log.warn("Error calculating age from birth date", e);
                            record.setAge(null);
                        }
                    }

                    // 设置档案号和门诊号
                    String patientIdSuffix = user.getId().substring(Math.max(0, user.getId().length() - 10));
                    record.setPatientFileNumber("P" + patientIdSuffix);

                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String datePrefix = LocalDateTime.now().format(formatter);
                    record.setOutpatientNumber("C" + datePrefix + patientIdSuffix.substring(0, 5));
                } else {
                    log.warn("User not found for ID: {}", order.getUserId());
                }
            } catch (Exception e) {
                log.warn("Error getting user info for ID: {}", order.getUserId(), e);
            }

            record.setVisitType("初诊");
            record.setStatus("INITIAL");
            record.setDiagnosisType("西医");
            record.setDiagnosisName("待诊断");
            record.setChiefComplaint("暂无主诉信息");
            record.setDelFlag(0); // 确保设置删除标记为0

            // 保存记录
            boolean saved = save(record);
            if (!saved) {
                log.error("Failed to save medical record for order ID: {}", orderId);
                throw new BusinessException("保存病历记录失败");
            }

            log.info("Created new medical record: {} for order ID: {}", record.getId(), orderId);
            return record;

        } catch (BusinessException be) {
            throw be;
        } catch (Exception e) {
            log.error("Error getting or creating medical record for order ID: {}", orderId, e);
            throw new BusinessException("获取或创建病历失败: " + e.getMessage());
        }
    }

    @Override
    public List<Map<String, Object>> getPatientOrderRecords(String patientId) {
        log.info("Getting patient order records for patient ID: {}", patientId);
        List<Map<String, Object>> result = new ArrayList<>();

        try {
            // 查询患者的所有病历记录
            QueryWrapper<MedicalRecord> query = new QueryWrapper<>();
            query.eq("user_id", patientId)
                 .orderByDesc("visit_time");

            List<MedicalRecord> records = list(query);
            log.info("Found {} medical records for patient ID: {}", records.size(), patientId);

            for (MedicalRecord record : records) {
                Map<String, Object> item = new HashMap<>();
                item.put("medicalRecord", record);

                // 关联查询挂号记录
                if (record.getOrderId() != null) {
                    try {
                        HospitalOrder order = hospitalOrderService.getById(record.getOrderId());
                        if (order != null) {
                            item.put("order", order);
                            log.debug("Added order info for medical record: {}", record.getId());
                        }
                    } catch (Exception e) {
                        log.error("Error getting order for ID: {}", record.getOrderId(), e);
                    }
                }

                result.add(item);
            }

            return result;
        } catch (Exception e) {
            log.error("Error getting patient order records for patient ID: {}", patientId, e);
            throw new BusinessException("获取患者挂号-病历关联记录失败: " + e.getMessage());
        }
    }
} 